// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#![no_std]
//! Core support code for code generated by `pw_format` macros
//!
//! The contents of this crate are primarily used by code which is generated
//! by macros using `pw_format`.

/// Trait used to produce printf style format strings for untyped format
/// specifiers.
///
/// The const [`PrintfFormatter::FORMAT_ARG`] is used to provide the printf
/// format specifier (i.e. the `d` in `%02d`) for a given type in Rust.  This
/// must be const so that it can be used to build static const format strings at
/// compile time.
pub trait PrintfFormatter {
    /// The format specifier for this type.
    const FORMAT_ARG: &'static str;
}

/// Trait used to produce printf style format strings for hex formatted untyped
/// format specifiers.
///
/// The const [`PrintfHexFormatter::FORMAT_ARG`] is used to provide the printf
/// format specifier (i.e. the `x` in `%02x`) for a given type in Rust.  This
/// must be const so that it can be used to build static const format strings at
/// compile time.
pub trait PrintfHexFormatter {
    /// The format specifier for this type.
    const FORMAT_ARG: &'static str;
}

/// Trait used to produce printf style format strings for upper case hex
/// formatted untyped format specifiers.
///
/// The const [`PrintfUpperHexFormatter::FORMAT_ARG`] is used to provide the
/// printf format specifier (i.e. the `x` in `%02x`) for a given type in Rust.
/// This must be const so that it can be used to build static const format
/// strings at compile time.
pub trait PrintfUpperHexFormatter {
    /// The format specifier for this type.
    const FORMAT_ARG: &'static str;
}

/// A helper to declare a [`PrintfFormatter`] trait and optionally
/// [`PrintfHexFormatter`] and [`PrintfUpperHexFormatter`] traits for a given
/// type.
macro_rules! declare_formatter {
    ($ty:ty, $specifier:literal, $hex_specifier:literal, $upper_hex_specifier:literal) => {
        impl PrintfFormatter for $ty {
            const FORMAT_ARG: &'static str = $specifier;
        }

        impl PrintfHexFormatter for $ty {
            const FORMAT_ARG: &'static str = $hex_specifier;
        }

        impl PrintfUpperHexFormatter for $ty {
            const FORMAT_ARG: &'static str = $upper_hex_specifier;
        }
    };

    ($ty:ty, $specifier:literal) => {
        impl PrintfFormatter for $ty {
            const FORMAT_ARG: &'static str = $specifier;
        }
    };
}

declare_formatter!(char, "c");
declare_formatter!(u8, "d");
declare_formatter!(i32, "d");
declare_formatter!(u32, "u", "x", "X");
declare_formatter!(i64, "d");
declare_formatter!(u64, "u", "x", "X");
declare_formatter!(usize, "u", "x", "X");
declare_formatter!(&str, "s");
